# # # This is a Windows PowerShell script that automatically collects all latest Zylinc log files to a ZIP file on your desktop. # To do that, run the script, and click YES to the first dialog. # # If you click NO, you'll get an option to view all latest log files in a list. You can then select one or more of the log files from that list, # and for example, open the selected files in Notepad or Notepad++, or copy the path of the selected log files to your clipboard. # # # -------------------- Test for PowerShell V3. Then ask the user if you want to: 1. Place log files in ZIP. 2: Open or examine latest log files -------------------- # To make log collection as simple as possible for the user, simply select YES to place all logs in a ZIP. Then, no further dialogs will be presented to the user. # To get to an advanced feature, that lets you open or examine latest log files, the user must first select NO, end then YES. Add-Type -AssemblyName PresentationFramework # Prevent the user from running this tool on PowerShell versions older than 3.0 if ($PSVersionTable.PSVersion.Major -lt 3) { $VersionErrorMessage="Unfortunately, you can't use this PowerShell script!`n`rTo use this script, your computer needs some updates.`n`rTo continue, you must use Windows Update to install PowerShell version 3.0 or newer." write-host $VersionErrorMessage -ForegroundColor Red [System.Windows.MessageBox]::Show($VersionErrorMessage, "Error", "Ok", "Error")|Out-Null $ActionZipLogs=$false $ActionExamineLogs=$false } else { if ([System.Windows.MessageBox]::Show("Do you want to place all log files in a ZIP file on your desktop?", "Collect log files or open latest log files", "YesNo", "Information") -eq 'Yes') { $ActionZipLogs=$true $ActionExamineLogs=$false } else { $ActionZipLogs=$false if ([System.Windows.MessageBox]::Show("Do you want to open and examine the latest log files?", "Collect log files or open latest log files", "YesNo", "Information") -eq 'Yes') { $ActionExamineLogs=$true } else { $ActionExamineLogs=$false } } } # -------------------- Dump relevant logfiles from docker to the folder LogsCollectedFromDocker so that we can collect them as if they were from a Zylinc Windows service -------------------- function CollectLogsFromDocker { # Create (and optionally overwrite) a single log file that contains redirected console output for the commands in the following. # In the file, each new command is separated by a line of ##########... followed by a line that begins with ########## + the command itself, followed by another line of ##########... # - get-date -format filedatetime # - docker system info # - docker stack ls # - docker service ls # - docker container ps -a --no-trunc # Foreach $CONTAINER_ID in GET_ALL_RUNNING_OR_STOPPED_CONTAINERS(): # - Display a "header" that contains STATUS (ex: running or exited), NAME, and IMAGE for the container with that $CONTAINER_ID # - docker container inspect $CONTAINER_ID # - Display the same "header" one more time # - docker container logs -t $CONTAINER_ID # Open the log file in Windows File Explorer # Export (and optionally overwrite) relevant Windows event logs to several .evtx files. (Ex: Application, Microsoft-Windows-Hyper-V-Compute-Operational, Microsoft-Windows-Hyper-V-Compute-Admin) mkdir "$Env:ProgramData\Zylinc" -force|out-null mkdir "$Env:ProgramData\Zylinc\LogsCollectedFromDocker"-force|out-null $DockerLogDumpTargetFolder="$Env:ProgramData\Zylinc\LogsCollectedFromDocker" $log_path= "$DockerLogDumpTargetFolder\Containers-Log Complete.log" $evtx_path="$DockerLogDumpTargetFolder\Containers-Log EventLog" function Write-header-invoke-cmd-and-redirect ($PowerShell_command) { Write-Host $PowerShell_command # Write a header that separates each new command as specified in a comment in the previous "#"*399+"`r`n"+"#"*10+" "+$PowerShell_command.replace("--format","`r`n"+"#"*10+" --format")+"`r`n"+"#"*399 >>$log_path $ScriptBlock= [Scriptblock]::Create($PowerShell_command) Invoke-Command -ScriptBlock $ScriptBlock >>$log_path } # Create a new empty file, and optionally overwrite it. $null>$log_path # Export (and optionally overwrite) relevant Windows event logs to several .evtx files. wevtutil export-log Application "$evtx_path Application.evtx" /ow wevtutil export-log Microsoft-Windows-Hyper-V-Compute-Admin "$evtx_path Microsoft-Windows-Hyper-V-Compute-Admin.evtx" /ow wevtutil export-log Microsoft-Windows-Hyper-V-Compute-Operational "$evtx_path Microsoft-Windows-Hyper-V-Compute-Operational.evtx" /ow # Set up output format templates $ps_outputformat_template="table {{printf \""""%.12s\"""" .ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Command}}\t{{.CreatedAt}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Size}}\t{{.Mounts}}\t{{.Networks}}" # $ps_outputformat_template is a docker golang template that returns all "docker container ps" fields as a table. It returns only the first 12 characters of the container id. # It doesn't return labels because if we need labels we can get them from the part of the logfile that contains "docker container inspect". It returns the most important columns first, for example ID, IMAGE and STATUS, and then the rest. $stats_outputformat_template="table {{printf \""""%.12s\"""" .ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" # $stats_outputformat_template is a docker golang template that returns all "docker container stats" fields as a table. It returns only the first 12 characters of the container id. # Do the actual logging, as specified in a previous comment. Write-header-invoke-cmd-and-redirect "get-date -format filedatetime" Write-header-invoke-cmd-and-redirect "docker system info" Write-header-invoke-cmd-and-redirect "docker stack ls" Write-header-invoke-cmd-and-redirect "docker service ls" Write-header-invoke-cmd-and-redirect "docker container ps -a --no-trunc --format ""$ps_outputformat_template""" Write-header-invoke-cmd-and-redirect "docker container stats -a --no-stream --no-trunc --format ""$stats_outputformat_template""" # Foreach $CONTAINER_ID in GET_ALL_RUNNING_OR_STOPPED_CONTAINERS(): docker container ps -qa| %{ # $command_get_status_name_and_image is a command that returns STATUS, NAME, and IMAGE, each on a new line, in the format "key: value" $command_get_status_name_and_image="docker container inspect $_ --format ""STATUS: {{println .State.Status }}NAME: {{println .Name}}IMAGE: {{.Config.Image}}""" Write-header-invoke-cmd-and-redirect $command_get_status_name_and_image Write-header-invoke-cmd-and-redirect "docker container inspect $_" Write-header-invoke-cmd-and-redirect $command_get_status_name_and_image Write-header-invoke-cmd-and-redirect "docker container logs -t $_" } } # function CollectLogsFromDocker # -------------------- Define the locations within the local file system, where this script will search for log files of different types -------------------- $ZyDeskRoot = $Env:AppData + "\Zylinc" $TomcatServiceRoot = $Env:ProgramFiles + "\Zylinc\ApacheInstances" $WindowsServiceRoot = $Env:ProgramData + "\Zylinc" # Test if Docker is installed, if so make a call to CollectLogsFromDocker to create "$Env:ProgramData\Zylinc\LogsCollectedFromDocker" and dump docker relevant logs to that folder. # This must be done before the check: if (-not (test-path $WindowsServiceRoot)) ... because we collect logs from docker as if they were logs from as Zylinc Windows service. if ((get-package -Name 'DockerMsftProvider' -ErrorAction SilentlyContinue) -and (get-service -Name 'Docker' -ErrorAction SilentlyContinue)) { if ($ActionZipLogs -or $ActionExamineLogs) # If user don't want to do anything, don't collect logs from docker and pretend docker is not installed { CollectLogsFromDocker $IsDockerInstalled=$true } else { $IsDockerInstalled=$false } } else { $IsDockerInstalled=$false } # If one or more folders doesn't exist, set it to "" so that it can be ignored in the following, at won't throw errors or exceptions. if (-not (test-path $ZyDeskRoot)) {$ZyDeskRoot=""} if (-not (test-path $TomcatServiceRoot)) {$TomcatServiceRoot=""} if (-not (test-path $WindowsServiceRoot)){$WindowsServiceRoot=""} # This folder may have been created by CollectLogsFromDocker in the previous, if docker is installed # -------------------- Find known text editors and set $EditorPath to the text editor with the highest priority -------------------- if (Test-Path "C:\Program Files\Notepad++\notepad++.exe") {$EditorPath="C:\Program Files\Notepad++\notepad++.exe"} else {if (Test-Path "C:\Program Files (x86)\Notepad++\notepad++.exe") { $EditorPath="C:\Program Files (x86)\Notepad++\notepad++.exe"} else {$EditorPath="C:\Windows\System32\notepad.exe"} } # -------------------- Initialize and populate array with selected log files from selected modules -------------------- Function Add-LogFileMetaDataToArray # This function helps to make code simple and readable, later in the script, when all log files and search filters are going to be defined. { param ($Handle,$Module,$Type,$WindowsServiceSubfolder,$Filter) $line=""|select Handle,Module,Type,WindowsServiceSubfolder,Filter,ActiveLogFilePath,LastWriteTime $line.Handle=$Handle # Specify the 2-4 letter acronym used by development team members $line.Module=$Module # Specify the name of the Module, as referred to in unified help $line.Type=$Type # Specify the type of the "log": (Windows | Exchange | Tomcat | ZyDesk) $line.WindowsServiceSubfolder=$WindowsServiceSubfolder # For $Type="Windows" or $Type="Exchange": Specify the name of the subfolder in C:\ProgramData\Zylinc. Otherwise specify "" $line.Filter=$Filter # Specify the directory filter to use, see PowerShell help for "get-childitem -filter" $line.ActiveLogFilePath="" # If a log file, or a set of log files, were found, ActiveLogFilePath will contain the full path to the most recent log file in the set. Otherwise it will contain "" $line.LastWriteTime="" # Contains last write time from the filesystem, for the file in ActiveLogFilePath, formatted as string, yyyy-MM-dd hh:mm:ss. Otherwise it will contain "" $script:array+=$line } $script:array = @() if ($ZyDeskRoot){ # "Handle" "Module" "Type" "WindowsServiceSubfolder" "Filter" Add-LogFileMetaDataToArray "ZDAU" "ZyDesk autoupdate" "ZyDesk" "" "autoupdate*.*" Add-LogFileMetaDataToArray "ZD" "ZyDesk main" "ZyDesk" "" "main*.*" Add-LogFileMetaDataToArray "ZDPJ" "ZyDesk pjsip" "ZyDesk" "" "pjsip*.*" Add-LogFileMetaDataToArray "ZDPB" "ZyDesk pjsip backup" "ZyDesk" "" "pjsipBackup*.*" Add-LogFileMetaDataToArray "ZDSU" "ZyDesk startup" "ZyDesk" "" "main_startup*.*" } if ($TomcatServiceRoot){ Add-LogFileMetaDataToArray "AUTH" "Authentication Server" "Tomcat" "" "Authentication.log*" Add-LogFileMetaDataToArray "CDS" "Cisco Directory Sync" "Tomcat" "" "CiscoDirSync.log*" Add-LogFileMetaDataToArray "CUX" "Cisco User Proxy" "Tomcat" "" "CiscoUserProxy.log*" Add-LogFileMetaDataToArray "GK" "Client Manager" "Tomcat" "" "ClientManager-main.log*" Add-LogFileMetaDataToArray "GK2" "Client Manager extra" "Tomcat" "" "ClientManager-extra.log*" Add-LogFileMetaDataToArray "ID" "ZyCore ID" "Tomcat" "" "ZyCoreID.log*" Add-LogFileMetaDataToArray "MP" "Messaging Portal" "Tomcat" "" "MessagingPortal.log*" Add-LogFileMetaDataToArray "SP" "Statistics Portal" "Tomcat" "" "StatisticsPortal.log*" Add-LogFileMetaDataToArray "ZDS" "ZyDataService" "Tomcat" "" "ZyDataService.log*" Add-LogFileMetaDataToArray "ZX" "Zylinc Proxy" "Tomcat" "" "ZylincProxy.log*" Add-LogFileMetaDataToArray "ZXC" "Zylinc Proxy Client" "Tomcat" "" "ZylincProxyClient.log*" Add-LogFileMetaDataToArray "ZYTE" "ZyTe" "Tomcat" "" "Zyte.log*" } if ($WindowsServiceRoot){ Add-LogFileMetaDataToArray "BDS" "BroadWorks Directory Sync" "Windows" "BroadWorksDirSync" "BroadWorksDirSyncLog*.*" Add-LogFileMetaDataToArray "BUP" "BroadWorks User Proxy" "Windows" "BroadWorksUserProxy" "BroadWorksUserProxyLog*.*" Add-LogFileMetaDataToArray "CAS" "Client API Service" "Windows" "ClientAPIService" "ClientApiService*.*" Add-LogFileMetaDataToArray "DBS" "Database Service" "Windows" "DatabaseService" "DatabaseService*Log*.*" Add-LogFileMetaDataToArray "DM" "Deployment Manager (GUI)" "Windows" "DeploymentManager" "DeploymentManagerLog*.*" Add-LogFileMetaDataToArray "DS" "Directory Server" "Windows" "DirectoryServer" "DirServLog_DirectoryServer*.*" Add-LogFileMetaDataToArray "EQH" "E-mail Queue Handler" "Windows" "EmailQueueHandler" "EmailQueueHandlerLog*.*" Add-LogFileMetaDataToArray "FAS" "Forwarding Activity Server" "Windows" "ForwardingActivityServer" "ForwardingActivityServer*log*.*" Add-LogFileMetaDataToArray "GW" "Gateway Service" "Windows" "Gateway" "Gateway*.txt" Add-LogFileMetaDataToArray "IDS" "Identity Server" "Windows" "IdentityServer" "IdentityServer*.txt" Add-LogFileMetaDataToArray "PS" "Provisioning Service" "Windows" "ProvisioningService" "MainLog*.*" Add-LogFileMetaDataToArray "LCQH" "SfB Chat Queue Handler" "Windows" "LyncChatQueueHandler" "LyncChatQueueHandlerLogFile*.*" Add-LogFileMetaDataToArray "LMN" "SfB MSPL Manager" "Windows" "LyncMsplManager" "LyncMsplManager*.txt" Add-LogFileMetaDataToArray "LUX" "SfB User Proxy" "Windows" "LyncUserProxy" "LyncUserProxy*.txt" Add-LogFileMetaDataToArray "MBP" "Mobile Presence" "Windows" "MobilePresence" "MobServLog_MobilePresence*.*" Add-LogFileMetaDataToArray "QM" "Queue Manager" "Windows" "QueueManager" "QueueManager*.log*" Add-LogFileMetaDataToArray "SM" "Service Manager" "Windows" "ServiceManager" "ServiceManager*.txt*" Add-LogFileMetaDataToArray "SUX" "SIP User Proxy" "Windows" "SipUserProxy" "SipUserProxyLogFile*.*" Add-LogFileMetaDataToArray "XQH" "XMPP Queue Handler" "Windows" "XmppQueueHandler" "XmppQueueHandler*.txt" Add-LogFileMetaDataToArray "XUX" "XMPP User Proxy" "Windows" "XmppUserProxy" "XmppUserProxy*.txt" Add-LogFileMetaDataToArray "ZG" "ZyGo" "Windows" "Zygo" "Zygo*.log*" # Add logfiles from all Exchange Sync Webservices that can be found to the array. Check recursively that at least one Exchange Sync Web Service "logs" subfolder exist: $ExchSync="ExchSync" # Name of sub folder that contains exchange logs if (get-childitem $WindowsServiceRoot\$ExchSync -Recurse -filter "log" -Attributes Directory) { # Find all of the Exchange Sync Web Service "logs" folders, and then extract a distinct list of Exchange Sync Webservice names from the folder names of logs.parent folders # Iterate through the list and for each entry, call Add-LogFileMetaDataToArray to add the logfiles for all found Exchange Sync Webservices to the array. $c=1 # Add an increasing number to the end of each handle's name to make each one unique, for example, EWS1, EWS2, EWS3. foreach ($EwsSyncName in (get-childitem $WindowsServiceRoot\$ExchSync -Recurse -filter "log" -Attributes Directory).parent|Select-Object name -unique) { $filtername=$EwsSyncName.name # "Handle""Module" "Type" "WindowsServiceSubfolder" "Filter" Add-LogFileMetaDataToArray "EWS$c" "Exchange Sync Web Service: $filtername" "Exchange" "$ExchSync" $filtername"*_log*.txt" $c=$c+1 } } } # If logs from docker were collected in the previous, add logs from docker to the array if ($IsDockerInstalled) { # "Handle" "Module" "Type" "WindowsServiceSubfolder" "Filter" Add-LogFileMetaDataToArray "DOCK" "Docker diagnostics and logs" "Windows" "LogsCollectedFromDocker" "Containers-Log Complete.log" } # -------------------- End of array population -------------------- # -------------------- Try to locate most the most recent logfile, for each row in the array, with the specified filter and folder. Then store its path and LastWriteTime in the array. Otherwise store "" in LastWriteTime and path -------------------- # Iterate through the array. For all the log files that match the filters in a row in the array, insert values for the most recent file into ActiveLogFilePath and LastWriteTime. for ($i=0; $i -lt $script:array.length; $i++) { $scanfolder=$null if ($script:array[$i].type -eq "ZyDesk") {$scanfolder=$ZyDeskRoot} if ($script:array[$i].type -eq "Windows") {$ScanFolder=$WindowsServiceRoot + "\" + $script:array[$i].WindowsServiceSubfolder} if ($script:array[$i].type -eq "Exchange") {$ScanFolder=$WindowsServiceRoot + "\" + $script:array[$i].WindowsServiceSubfolder} if ($script:array[$i].type -eq "Tomcat") {$ScanFolder=$TomcatServiceRoot} if ($scanfolder) { $activelogfile=get-childitem $scanfolder -filter $script:array[$i].Filter -rec|Sort{[datetime]$_.LastWriteTime}-desc|Select-Object -First 1 # Out of all matching log files for a row in the array, select the most recent one (LastWriteTime) if ($activelogfile) { $script:array[$i].ActiveLogFilePath=$activelogfile.FullName $script:array[$i].LastWriteTime= $activelogfile.LastWriteTime.Tostring("yyyy-MM-dd hh:mm:ss") } else { $script:array[$i].ActiveLogFilePath="" # Store "" so that errors or exceptions can be prevented in the following $script:array[$i].LastWriteTime="" } } else { write-host "Internal error: Wrong type: ("$script:array[$i].type") for module: ("$script:array[$i].module")" -ForegroundColor Red } } # -------------------- Present log files in a GUI gridview and let the user select none, one, or multiple logfiles -------------------- if ($ActionExamineLogs) # Only if the user wants to open or examine latest log files { if ($script:array) # Only if at least one log file could be found { $todo=$null # This string contains a list of choices that the user wants to do with the selected log files $clipstring="" # Build the string to copy to clipboard (the user can select an action that copies the paths to the selected log files to the clipboard) Foreach ($selectedfile in ($script:array|select Module,Handle,Type,ActiveLogFilePath,LastWriteTime|Out-GridView -PassThru -Title "Select one or more log files and click OK")) { # Iterate though the selected log files # In another GUI gridview, present choices about what to do with the previously selected logfiles. User can select none, one or multiple actions to carry out on the selected files. if ($todo -eq $null) # Present gridview for the first iteration, and assume the same choice in any future iterations: { $actions = @() $line=""|select Choice,Action;$line.Choice='Edit with Notepad++' ;$line.Action='Open selected files in Notepad++ or alternatively in Windows Notepad.exe';$actions+=$line $line=""|select Choice,Action;$line.Choice='Explore' ;$line.Action='Open containing folder in Windows Explorer and select the file';$actions+=$line $line=""|select Choice,Action;$line.Choice='Open' ;$line.Action='Open selected files in the associated application';$actions+=$line $line=""|select Choice,Action;$line.Choice='Copy as path' ;$line.Action='Copy selected paths to clipboard';$actions+=$line $line=""|select Choice,Action;$line.Choice='Show rolling tail' ;$line.Action='Show rolling log tail in a new window';$actions+=$line $todo=$actions|Out-GridView -PassThru -Title "Select one or more actions to do with the selected log files" if ($todo -eq $null) # If user selects CANCEL: { $line=""|select Choice,Action;$line.Choice='Cancel' # Prevents any action from being done in the following because Cancel isn't assigned to any action $todo+=$line } } # -------------------- Action: Edit with Notepad++ -------------------- if ($todo.choice -eq "Edit with Notepad++") # Open in text editor { if ($selectedfile.ActiveLogFilePath) # Only rows that contains a path to a logfile can be opened { if (test-path $selectedfile.ActiveLogFilePath) # Only files that exist can be opened { $editfile=$selectedfile.ActiveLogFilePath & $editorpath `"$editfile`" # Use the specified editor to open the log file } } } # -------------------- Action: Explore -------------------- if ($todo.choice -eq "Explore") # Open containing folder in windows explorer with the file selected { if ($selectedfile.ActiveLogFilePath) # Only rows that contains a path to a logfile can be opened { if (test-path $selectedfile.ActiveLogFilePath) # Only files that exist can be opened { $explorefile=$selectedfile.ActiveLogFilePath & explorer.exe /select,`"$explorefile`" # Open containing folder in Windows explorer with the file selected } } } # -------------------- Action: Open -------------------- if ($todo.choice -eq "Open") # Open selected file with whatever program that is associated with its filetype { if ($selectedfile.ActiveLogFilePath) # Only rows that contains a path to a logfile can be opened { if (test-path $selectedfile.ActiveLogFilePath) # Only files that exist can be opened { $explorefile=$selectedfile.ActiveLogFilePath & $explorefile # Open file with its associated program } } } # -------------------- Action: Copy as path -------------------- if ($todo.choice -eq "Copy as path") # Copy selected paths to clipboard. You can select more than one file, and a list of paths will be copied to the clipboard { if ($selectedfile.ActiveLogFilePath) # Only rows that contains a path to a logfile can be copied to the clipboard { if ($clipstring) { $clipstring=$clipstring +"`r`n"+ $selectedfile.ActiveLogFilePath # Append linefeed and then the path, when you are adding more than a single path } else # Add the first path without linefeed { $clipstring=$selectedfile.ActiveLogFilePath # If you copy a single path, no linefeeds should be added } Set-Clipboard $clipstring } } # -------------------- Action: Show log tail in PowerShell -------------------- if ($todo.choice -eq "Show rolling tail") # Open an auto-updating log tail window with powershell { if ($selectedfile.ActiveLogFilePath) # Only rows that contains a path to a logfile can be opened { if (test-path $selectedfile.ActiveLogFilePath) # Only files that exist can be opened { # Open an auto-updating log tail window in powershell $command="-command `$Host.UI.RawUI.WindowTitle='$($selectedfile.Module) log - rolling tail ($($selectedfile.ActiveLogFilePath))';get-content '$($selectedfile.ActiveLogFilePath)' -Wait" start -FilePath PowerShell.exe -ArgumentList $command } } } } } else {[System.Windows.MessageBox]::Show("No relevant log files were found on this computer.","Open latest log files","Ok","Exclamation")} } # -------------------- Copy the containing folders of all known active log files to a folder on the desktop, and then ZIP that folder -------------------- if ($ActionZipLogs) # Only if the user wants to place all log files in a ZIP { # -------------------- Make a new folder on the desktop, and include the current date and time in the name of that folder -------------------- $LogDumpTargetFolder=get-date -Format "yyyy-MM-dd HH-mm-ss" $LogDumpTargetFolder=[Environment]::GetFolderPath("Desktop")+"\Logdump $LogDumpTargetFolder" mkdir $LogDumpTargetFolder -force|out-null write-host "Target folder is $LogDumpTargetFolder" write-host # -------------------- Place all environment variables and their values in a log file -------------------- # Dump environment variables and their values into EnvironmentVars.log. # Environment variables are useful because they allow support engineers to find, for example, computername and username in log files on other computers. # Clientname and sessionname is useful if you need to know if a Terminal Server or Citrix Session were active. write-host "Environment variables log file..." Get-ChildItem Env:|select-object Key, Value|Format-Table -AutoSize -Wrap|Out-File -Width 225 -append "$LogDumpTargetFolder\EnvironmentVars.log" # -------------------- Place the output of the systeminfo command in a log file -------------------- # Dump systeminfo write-host "System info log file..." systeminfo|Out-File -Width 225 "$LogDumpTargetFolder\SystemInfo.log" # -------------------- Place the PowerShell version info in a log file -------------------- # Dump PowerShell version write-host "PowerShell version info log file..." $PSVersionTable|Out-File -Width 225 "$LogDumpTargetFolder\PowerShellVersionInfo.log" # -------------------- Place a list of all installed software, its vendor and version in a log file -------------------- # Dump list of installed software write-host "Installed software and framework versions log file..." Get-WmiObject -Class Win32_Product|sort-object Vendor,Name,Version,IdentifyingNumber|select-object Vendor,Name,Version,IdentifyingNumber|Format-Table -AutoSize -Wrap|Out-File -Width 225 -Append "$LogDumpTargetFolder\InstalledSoftwareAndFrameworkVersions.log" # -------------------- Place a list of all running processes, ordered by memory use descending in a log file -------------------- write-host "CPU and memory use log file..." # Dump the results of get-process ordered by memory desc "Handles: The number of handles that the process has opened." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "NPM(K): The amount of non-paged memory that the process is using, in kilobytes." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "PM(K): The amount of pageable memory that the process is using, in kilobytes." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "WS(K): The size of the working set of the process, in kilobytes. The working set consists of the pages of memory that were recently referenced by the process." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "VM(M): The amount of virtual memory that the process is using, in megabytes. Virtual memory includes storage in the paging files on disk." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "CPU(s): The amount of processor time that the process has used on all processors, in seconds." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "ID: The process ID (PID) of the process." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "ProcessName: The name of the process." |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" "`r`nAll processes ordered by memory WS(K) descending:" |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" get-process|sort-object WS -Descending|Format-Table -AutoSize -Wrap |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" # -------------------- Place a list of all running processes, ordered by CPU usage descending in the same log file -------------------- # Dump the results of get-process ordered by CPU desc "`r`nAll processes ordered by CPU(s) descending:" |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" get-process|sort-object -Property CPU -Descending|Format-Table -AutoSize -Wrap |Out-File -Width 225 -Append "$LogDumpTargetFolder\MemAndCPU.log" # -------------------- Place a list of Zylinc related services that are not started in a log file -------------------- # Dump the results of Zylinc related services that are not started: write-host "Stopped services log file..." "The following Zylinc related services are not started. This is very likely an error:" |Out-File -Width 225 -Append "$LogDumpTargetFolder\ServiceStatus.log" gwmi win32_service|where-object{ ($_.pathname -Like '*zylinc*')-or($_.pathname -Like '*apache*tomcat*')-or($_.pathname -Like '*binn*sqlservr.exe*')-and(-not $_.started) }|select-object DisplayName,Name,Started,State,ProcessId,StartMode,DelayedAutoStart|Format-Table -AutoSize -Wrap |Out-File -Width 225 -Append "$LogDumpTargetFolder\ServiceStatus.log" # -------------------- Place a list of Zylinc related services that is currently started in a log file -------------------- # Dump the results of Zylinc related services that are started: write-host "Started services log file..." "The following Zylinc related services are started:" |Out-File -Width 225 -Append "$LogDumpTargetFolder\ServiceStatus.log" gwmi win32_service|where-object{ ($_.pathname -Like '*zylinc*')-or($_.pathname -Like '*apache*tomcat*')-or($_.pathname -Like '*binn*sqlservr.exe*')-and($_.started) }|select-object DisplayName,Name,Started,State,ProcessId,StartMode,DelayedAutoStart|Format-Table -AutoSize -Wrap |Out-File -Width 225 -Append "$LogDumpTargetFolder\ServiceStatus.log" # -------------------- Place the part of the Windows registry that contains settings about Tomcat instances in a log file -------------------- # Dump Tomcat registry settings in .REG format to TomcatRegistrySettings.log and/or TomcatRegistrySettingsX86.log. # This is useful because it allows support engineers to view versions of Java and Tomcat, and it allows to view values of critical memory parameters, for example max. memory. write-host "Tomcat registry settings log file..." if (test-path 'HKLM:\SOFTWARE\WOW6432Node\Apache Software Foundation') {reg export 'HKLM\SOFTWARE\WOW6432Node\Apache Software Foundation' "$LogDumpTargetFolder\TomcatRegistrySettings.log" |Out-Null} if (test-path 'HKLM:\SOFTWARE\Apache Software Foundation') {reg export 'HKLM\SOFTWARE\Apache Software Foundation' "$LogDumpTargetFolder\TomcatRegistrySettingsX86.log"|Out-Null} # -------------------- Make a human readable text file, FileCopy.log, about the log files that were collected -------------------- write-host "FileCopy log file..." "Logfiles collected via `"Collect Zylinc Logfiles PowerShell Script version 1.1.0.6`", available via `"Zylinc Unified Help`" web portal at `"https://help.zylinc.com`""|Out-File -Width 225 "$LogDumpTargetFolder\FileCopy.log" # -------------------- Add a table of all the active log files that were found to FileCopy.log -------------------- # Output a table with all available information about the active log files, that were found by the specified filter rules: "`r`nThe following active logfiles were found:"|Out-File -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append $script:array|select-object Module,Handle,Type,ActiveLogFilePath,LastWriteTime|where ActiveLogFilePath|Format-Table -AutoSize -Wrap|Out-file -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append # -------------------- Add a table of all the log files that couldn't be found to FileCopy.log -------------------- # Output a table with information about which log files that couldn't bet found by the specified filter rules: "The following logfiles couldn't be found, most probably because the service isn't installed or was never started or couldn't start:"|Out-File -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append $script:array|where ActiveLogFilePath -eq ''|select-object Module,Handle,Type|Format-Table -AutoSize -Wrap|Out-file -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append # -------------------- Add a list to FileCopy.log of the folders that contained at least one active log file and therefore were copied and zipped -------------------- # Output a list of all folders that contain at least one of the active log files found by the specified filter rules: "The following folders contain active log files and have therefore been copied to $LogDumpTargetFolder`:`r`n"|Out-File -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append # -------------------- Populate an array that uniquely contains only those folders that contain any of the known active logfiles -------------------- # This will exclude log folders for uninstalled services, or log folders for services where a newer logfile of the same service has been written to, but at another path # This is because we don't want to collect log files left behind in previous Tomcat instances, or in previous instances of log folders for older versions of services $arrUniqueFoldersAllActiveLogFiles=@() foreach ($folderContainsAnActiveLogfile in $script:array|where-object ActiveLogFilePath -NE ''|select-object ActiveLogFilePath) { $arrUniqueFoldersAllActiveLogFiles+=(get-item $folderContainsAnActiveLogfile.ActiveLogFilePath).Directory.FullName # select the containing folder path for all active log files } $arrUniqueFoldersAllActiveLogFiles=$arrUniqueFoldersAllActiveLogFiles|select -Unique # remove doublets # -------------------- Iterate through that array and copy each folder to a new target folder with a nice decluttered name -------------------- $arrFolderTable = @() $arrUniqueFoldersAllActiveLogFiles|%{ # -------------------- Start of make nice folder name -------------------- # Declutter the complex folder structure so that log file files are collected into new one dimensional folder, with nice and readable names, for example: # C:\Users\Administrator\AppData\Roaming\Zylinc\Zydesk\Log -----> ZYDESK logs # C:\Program Files\Zylinc\ApacheInstances\ZyTomcat1-8080-8443\logs -----> TOMCAT ZyTomcat1-8080-8443 logs # C:\ProgramData\Zylinc\DeploymentManager\2.1.178.0 -----> DeploymentManager 2.1.178.0 logs # C:\ProgramData\Zylinc\DirectoryServer\1.6.24.0\DirectoryServer\Log -----> DirectoryServer 1.6.24.0 logs # C:\ProgramData\Zylinc\Zygo\1.5.7.0\Zygo\log -----> Zygo 1.5.7.0 logs # C:\ProgramData\Zylinc\ExchSync\1.4.68.0\ExchSync\Exchange\log -----> ExchSync 1.4.68.0.Exchange logs $FolderWithAnActiveLogfile= $_ # In the following, we use this string to manipulate the folder names in several different operational steps # Declutter folder names by removing the obvious root folder names from the beginning of all the paths if ($ZyDeskRoot -ne '') {$FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.replace($ZyDeskRoot, 'ZYDESK')} if ($TomcatServiceRoot -ne '') {$FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.replace($TomcatServiceRoot, 'TOMCAT')} if ($WindowsServiceRoot -ne '') {$FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.replace($WindowsServiceRoot+'\','')} # Remove the following from folder name: "\" "\logs" "\log" # Replace ":" with "" # Handle common uppercase and lowercase situations to avoid doublet names for example, between Zydesk/ZYDSEK or Logs/logs $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace('\Logs','') $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace('\logs','') $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace('\log','') $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace('\Log','') $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace(':','') $FolderWithAnActiveLogfile=$FolderWithAnActiveLogfile.Replace('Zydesk','ZYDESK') # Split at the "\" character, and if more than one folder within the path contains the same name as another folder within the path, only return the unique folder names $NiceFolderName='' $FolderWithAnActiveLogfile.split('\')|select -Unique|%{ # Then make it all in to a simple folder name and store that name in $NiceFolderName $NiceFolderName=$NiceFolderName + $_ + " "} $NiceFolderName=$NiceFolderName + "logs" # -------------------- End of make nice folder name -------------------- # -------------------- Copy each folder that contains an active log file to a new sub folder with a nice decluttered name -------------------- Write-host "...copying from $_ to $nicefoldername" Copy-Item $_ -Destination "$LogDumpTargetFolder\$NiceFolderName" -Recurse $arrFolderTable += [pscustomobject]@{SourceFolder=$_;TargetFolder=$nicefoldername} } $arrFolderTable|Format-Table|Out-file -Width 225 "$LogDumpTargetFolder\FileCopy.log" -Append # -------------------- Zip compress the $LogDumpTargetFolder -------------------- write-host "Compressing..." Compress-Archive -Path "$LogDumpTargetFolder" -DestinationPath "$LogDumpTargetFolder.zip" if (Test-Path ("$LogDumpTargetFolder.zip")) # To prevent errors on previous PowerShell versions, keep the folder if the Zip failed. { remove-item "$LogDumpTargetFolder" -Recurse } # -------------------- Show message to the user, that process is done and where to find the file -------------------- $ZipName=$LogDumpTargetFolder.replace([Environment]::GetFolderPath("Desktop")+"\",'')+".zip" $DoneMessage="The log file collection is now complete.`r`nA zip file with the name $ZipName has been placed on your desktop." write-host $DoneMessage -ForegroundColor Green [System.Windows.MessageBox]::Show($DoneMessage, "Collect log files or open latest log files", "ok", "Information") } # #